package com.hx.localmiaosha.service.imp;

import com.alibaba.fastjson.JSON;
import com.hx.common.common.SnowflakeIdWorker;
import com.hx.common.common.enums.ResultStatus;
import com.hx.common.constant.GoodServerConstant;
import com.hx.common.domain.MiaoshaGoods;
import com.hx.common.exception.GlobleException;
import com.hx.common.to.OrderMessageTo;
import com.hx.common.to.RedisGoodsTo;
import com.hx.localmiaosha.service.LocalMiaoshaGoodsService;
import com.hx.localmiaosha.service.LocalOrderService;
import com.hx.localmiaosha.service.MiaoShaCheckService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Author wonghiu
 * @Date 2021/8/8 16:30
 * @Version 1.0.1
 */
@Slf4j
@Service("miaoShaCheckService")
public class MiaoShaCheckServiceImp implements MiaoShaCheckService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private LocalMiaoshaGoodsService miaoshaGoodsService;
    @Autowired
    private LocalOrderService orderService;

    @Override
    public Long killForTestNoCacheLocal(Long goodsId) {
        // ThreadLocal要在方法内获取
        // 获取用户信息
//        MiaoshaUser loginUserVo = AuthInterceptor.loginUser.get();
        // 获取商品信息
        MiaoshaGoods miaoshaGoods = miaoshaGoodsService.getGoodsById(goodsId);
        if (miaoshaGoods == null) {
            throw new GlobleException(ResultStatus.MIAOSHA_FAIL);
        } else {
            // 校验合法性
            long startDte = miaoshaGoods.getStartDate().getTime();
            long endDate = miaoshaGoods.getEndDate().getTime();
            long nowDate = new Date().getTime();

            long ttl = endDate - nowDate;
            // 校验时间
            if (nowDate >= startDte && nowDate <= endDate) {

                // TODO 验证购买数量不超过限制
                // 验证是否已经买过，只要秒杀成功就去占位。 userId_skuId
//                String redisKey = GoodServerConstant.GOODS_USER + loginUserVo.getId() + "_" + goodsId;

//                    Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey,"1",ttl, TimeUnit.MILLISECONDS);
                Boolean aBoolean = true;
                if (aBoolean != null) {
                    // 判断是否剩余库存
                    if (miaoshaGoods.getStockCount()<=0){
                        throw new GlobleException(ResultStatus.GOODS_NO_ENOUGH);
                    }
                    // 校验完成，生成订单号进行订单创建
                    else {
                        try {
                            long orderId = SnowflakeIdWorker.getOrderId(1, 1);
                            OrderMessageTo orderMessageTo = new OrderMessageTo();
                            orderMessageTo.setGoodsId(goodsId);
                            orderMessageTo.setOrderId(orderId);
                            orderMessageTo.setCountGoods(1);
//                            orderMessageTo.setUserId(loginUserVo.getId());

                            if (miaoshaGoodsService.reduceStock(orderMessageTo)) {
                                orderService.createPreOrderNoCache(orderMessageTo);
                                orderService.finishPreOrder(orderMessageTo);
                            }
                            return orderId;
                        } catch (Exception e) {
                            log.info(e.toString());
                            throw new GlobleException(ResultStatus.MIAOSHA_FAIL);
                        }
                    }
                } else {
                    throw new GlobleException(ResultStatus.REPEATE_MIAOSHA);
                }
            }
        }

        throw new GlobleException(ResultStatus.MIAOSHA_GETGOODINFO_FAIL);
    }
    @Override
    public Long killForTestWithCacheLocal(Long goodsId) {
        // ThreadLocal要在方法内获取
        // 获取用户信息
//        MiaoshaUser loginUserVo = AuthInterceptor.loginUser.get();
        // 从redis中获取商品信息
        String json = redisTemplate.opsForValue().get(GoodServerConstant.GOODS_INFO_PREFIX + goodsId);
        RedisGoodsTo miaoshaGoods = JSON.parseObject(json, RedisGoodsTo.class);

        if (miaoshaGoods == null) {
            throw new GlobleException(ResultStatus.MIAOSHA_FAIL);
        } else {
            // 校验合法性
            long startDte = miaoshaGoods.getStartDate().getTime();
            long endDate = miaoshaGoods.getEndDate().getTime();
            long nowDate = new Date().getTime();

            long ttl = endDate - nowDate;
            // 校验时间
            if (nowDate >= startDte && nowDate <= endDate) {

                // TODO 验证购买数量不超过限制
                // 验证是否已经买过，只要秒杀成功就去占位。 userId_skuId
//                String redisKey = GoodServerConstant.GOODS_USER + loginUserVo.getId() + "_" + goodsId;

//                    Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey,"1",ttl, TimeUnit.MILLISECONDS);
                Boolean aBoolean = true;
                if (aBoolean != null) {
                    // 判断是否剩余库存
                    //占位成功说明从来没有买过,通过信号量锁库存
                    RSemaphore semaphore = redissonClient.getSemaphore(GoodServerConstant.GOODS_STOCK_PREFIX + goodsId);

                    // 校验完成，生成订单号进行订单创建
                    try {
                        // 抢信号量库存
                        if (!semaphore.tryAcquire(1, 100, TimeUnit.MILLISECONDS)) {
                            log.info("库存不足");
                            throw new GlobleException(ResultStatus.GOODS_NO_ENOUGH);
                        }
                        long orderId = SnowflakeIdWorker.getOrderId(1, 1);
                        OrderMessageTo orderMessageTo = new OrderMessageTo();
                        orderMessageTo.setGoodsId(goodsId);
                        orderMessageTo.setOrderId(orderId);
                        orderMessageTo.setCountGoods(1);
//                        orderMessageTo.setUserId(loginUserVo.getId());
                        if (miaoshaGoodsService.reduceStock(orderMessageTo)) {
                            orderService.createPreOrderNoCache(orderMessageTo);
                            orderService.finishPreOrder(orderMessageTo);
                        }
                        return orderId;
                    } catch (Exception e) {
                        log.info(e.toString());
                        throw new GlobleException(ResultStatus.MIAOSHA_FAIL);
                    }
                } else {
                    throw new GlobleException(ResultStatus.REPEATE_MIAOSHA);
                }
            }
        }

        throw new GlobleException(ResultStatus.MIAOSHA_GETGOODINFO_FAIL);
    }
}
